package star.cloud.asme.flowable.task;

import jakarta.transaction.Transactional;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.flowable.engine.*;
import org.flowable.engine.runtime.ChangeActivityStateBuilder;
import org.flowable.engine.runtime.ProcessInstance;
import org.flowable.engine.task.Comment;
import org.flowable.engine.task.Event;
import org.flowable.task.api.Task;
import org.flowable.task.api.TaskInfo;
import org.flowable.task.api.TaskQuery;
import org.flowable.task.api.history.HistoricTaskInstance;
import org.springframework.stereotype.Service;
import star.cloud.asme.base.dto.Result;
import star.cloud.asme.base.fowable.VO.TaskInstanceVO;
import star.cloud.asme.base.fowable.baseInterface.FlowableVOGeneratorService;
import star.cloud.asme.flowable.task.DTO.CompleteTaskDTO;

import java.util.*;

@Service
@RequiredArgsConstructor
@Slf4j
public class HqTaskServiceImpl implements HqTaskService {

    private final TaskService taskService;
    private final HistoryService historyService;
    private final IdentityService identityService;
    private final RuntimeService runtimeService;
    private final FlowableVOGeneratorService voGeneratorService;

    @Override
    public Result<TaskInstanceVO> getOneByCondition(String columnName, Object columnValue) {
        org.flowable.task.api.TaskQuery taskQuery = taskService.createTaskQuery();
        switch (columnName) {
            case "id" -> taskQuery.taskId(columnValue.toString());
            case "name" -> taskQuery.taskName(columnValue.toString());
            default -> log.info("没有的条件类型");
        }
        return Result.ok();

    }

    @Override
    public Result<List<TaskInstanceVO>> getListByCondition(String columnName, Object columnValue) {

        TaskQuery taskQuery = taskService.createTaskQuery();

        switch (columnName) {
            case "id" -> taskQuery.taskId(columnValue.toString());
            case "name" -> taskQuery.taskName(columnValue.toString());
            case "assignee" -> taskQuery.taskAssignee(columnValue.toString());
            case "processInstanceId" -> taskQuery.processInstanceId(columnValue.toString());
        }

        List<Task> taskList = taskQuery.orderByTaskCreateTime().asc().list();

        List<TaskInstanceVO> taskInstanceVOList = new ArrayList<>();

        taskList.forEach(task -> taskInstanceVOList.add(voGeneratorService.generateTaskVO(task.getId())));

        return Result.ok(taskInstanceVOList);
    }

    @Override
    @Transactional(rollbackOn = Exception.class)
    public Result<?> doTask(CompleteTaskDTO completeTaskDTO) {
        identityService.setAuthenticatedUserId(completeTaskDTO.getUserUsernameFrom());
        return switch (completeTaskDTO.getCommentType()) {
            case "通过" -> completeTask(completeTaskDTO);
            case "驳回", "撤回" -> moveTask(completeTaskDTO);
            case "转办" -> changeAssignee(completeTaskDTO);
            case "沟通" -> delegateTask(completeTaskDTO);
            case "回复" -> resolveTask(completeTaskDTO);
            case "废弃" -> deleteProcessInstance(completeTaskDTO);
            case "暂停" -> suspendProcessInstance(completeTaskDTO);
            case "激活" -> activateProcessInstance(completeTaskDTO);
            default -> Result.error();
        };
    }

    @Override
    public Result<List<TaskInstanceVO>> getCommentListByProcessInstanceId(String processInstanceId) {
        List<HistoricTaskInstance> taskInstances = historyService.createHistoricTaskInstanceQuery().processInstanceId(processInstanceId).orderByTaskCreateTime().asc().list();
        historyService.createHistoricTaskInstanceQuery().processInstanceId(processInstanceId).orderByTaskCreateTime().asc().list();
        if (taskInstances.isEmpty()) {
            return Result.ok(null);
        } else {
            List<TaskInstanceVO> taskInstanceVOList = new ArrayList<>();
            taskInstances.forEach(task -> {
                List<Event> taskEvents = taskService.getTaskEvents(task.getId());
                List<Comment> commentList = taskEvents.stream().map(taskEvent -> taskService.getComment(taskEvent.getId()))//
                        .filter(taskEvent -> !Objects.equals(taskEvent.getType(), "event"))//
                        .sorted(Comparator.comparing(Comment::getTime)).toList();
                taskInstanceVOList.addAll(voGeneratorService.generatetCommentVOList(task, commentList));
            });
            return Result.ok(taskInstanceVOList);
        }
    }

    //办理任务
    @Transactional(rollbackOn = Exception.class)
    protected Result<?> completeTask(CompleteTaskDTO completeTaskDTO) {
        addComment(completeTaskDTO);
        taskService.complete(completeTaskDTO.getTaskId(), completeTaskDTO.getUserUsernameTo(), completeTaskDTO.getVariables());
        return Result.ok();
    }

    //拒绝或者撤回任务
    @Transactional(rollbackOn = Exception.class)
    protected Result<?> moveTask(CompleteTaskDTO completeTaskDTO) {
        List<Task> taskList = taskService.createTaskQuery().processInstanceId(completeTaskDTO.getProcessInstanceId()).list();
        List<String> taskDefinitionIdList = taskList.stream().map(TaskInfo::getTaskDefinitionKey).toList();
        ChangeActivityStateBuilder stateBuilder = runtimeService.createChangeActivityStateBuilder().processInstanceId(completeTaskDTO.getProcessInstanceId());
        if (taskDefinitionIdList.size() == 1) {
            if (Objects.equals(taskDefinitionIdList.get(0), "userTask_prepare")) {
                return Result.error().msg("已经位于起草节点了，不可再撤回。");
            }
            addComment(completeTaskDTO);
            stateBuilder.moveActivityIdTo(taskDefinitionIdList.get(0), "userTask_prepare").changeState();
        } else {
            addComment(completeTaskDTO);
            stateBuilder.moveActivityIdsToSingleActivityId(taskDefinitionIdList, "userTask_prepare").changeState();
        }
        return Result.ok();
    }


    private void addComment(CompleteTaskDTO completeTaskDTO) {
        taskService.addComment(completeTaskDTO.getTaskId(), completeTaskDTO.getProcessInstanceId(), completeTaskDTO.getCommentType(), completeTaskDTO.getCommentMessage() == null ? completeTaskDTO.getCommentType() : completeTaskDTO.getCommentMessage());
    }

    //转办任务
    @Transactional(rollbackOn = Exception.class)
    protected Result<?> changeAssignee(CompleteTaskDTO completeTaskDTO) {
        taskService.setAssignee(completeTaskDTO.getTaskId(), completeTaskDTO.getUserUsernameTo());
        List<Event> taskEvents = taskService.getTaskEvents(completeTaskDTO.getTaskId());
        Event event = taskEvents.get(0);
        Comment comment = taskService.getComment(event.getId());
        comment.setType(completeTaskDTO.getCommentType());
        comment.setFullMessage(completeTaskDTO.getCommentMessage());
        comment.setProcessInstanceId(completeTaskDTO.getProcessInstanceId());
        taskService.saveComment(comment);
        return Result.ok();
    }

    //沟通任务
    @Transactional(rollbackOn = Exception.class)
    protected Result<?> delegateTask(CompleteTaskDTO completeTaskDTO) {
        addComment(completeTaskDTO);
        taskService.delegateTask(completeTaskDTO.getTaskId(), completeTaskDTO.getUserUsernameTo());
        return Result.ok();
    }


    //沟通任务
    @Transactional(rollbackOn = Exception.class)
    protected Result<?> resolveTask(CompleteTaskDTO completeTaskDTO) {
        addComment(completeTaskDTO);
        taskService.resolveTask(completeTaskDTO.getTaskId(), completeTaskDTO.getVariables());
        return Result.ok();
    }

    private Result<?> deleteProcessInstance(CompleteTaskDTO completeTaskDTO) {
        addComment(completeTaskDTO);
        runtimeService.deleteProcessInstance(completeTaskDTO.getProcessInstanceId(), completeTaskDTO.getCommentMessage());
        return Result.ok();
    }

    //暂停任务
    private Result<?> suspendProcessInstance(CompleteTaskDTO completeTaskDTO) {
        ProcessInstance processInstance = runtimeService.createProcessInstanceQuery().processInstanceId(completeTaskDTO.getProcessInstanceId()).singleResult();
        if (processInstance != null && !processInstance.isSuspended()) {
            addComment(completeTaskDTO);
            runtimeService.suspendProcessInstanceById(completeTaskDTO.getProcessInstanceId());
            return Result.ok();
        } else {
            return Result.error().msg("流程已经处于暂停状态");
        }
    }

    //激活任务
    protected Result<?> activateProcessInstance(CompleteTaskDTO completeTaskDTO) {
        ProcessInstance processInstance = runtimeService.createProcessInstanceQuery().processInstanceId(completeTaskDTO.getProcessInstanceId()).singleResult();
        if (processInstance != null && processInstance.isSuspended()) {
            runtimeService.activateProcessInstanceById(completeTaskDTO.getProcessInstanceId());
            addComment(completeTaskDTO);
            return Result.ok();
        } else {
            return Result.error().msg("流程已经处于激活状态");
        }
    }

}
